package com.${ltdAbbr}.xiao.${module}.web.config;

import java.sql.SQLException;

import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import com.alibaba.druid.pool.DruidDataSource;
import com.yt.xiao.database.config.XYAbstractMybatisConfig;

/**
 * 核心配置，配置数据源 事物 sqlsession
 * 
 * @author QIANG
 *
 */
@Configuration
@EnableTransactionManagement    
public class DataBaseConfiguration extends XYAbstractMybatisConfig {

    <#noparse>@Value("${</#noparse>${module}.datasource.url<#noparse>}")</#noparse>
    private String ${module}ServiceUrl;

    <#noparse>@Value("${</#noparse>${module}.datasource.username<#noparse>}")</#noparse>
    private String ${module}ServiceUsername;

    <#noparse>@Value("${</#noparse>${module}.datasource.password<#noparse>}")</#noparse>
    private String ${module}ServicePassword;

    // 注册dataSource
    @Primary
    @Bean(name = "${module}Datasource", initMethod = "init", destroyMethod = "close")
    public DruidDataSource create${module?cap_first}Datasource() {
        return super.createDataSource(${module}ServiceUrl, ${module}ServiceUsername, ${module}ServicePassword);
    }

    @Primary
    @Bean(name = "${module}SqlSessionFactory")
    public SqlSessionFactory create${module?cap_first}SqlSessionFactory() throws Exception {
        return super.createSqlSessionFactory(create${module?cap_first}Datasource(), "classpath*:mybatis/**/*.xml");
    }

    @Primary
    @Bean(name="${module}TransactionManager")
    public PlatformTransactionManager create${module?cap_first}TransactionManager() throws SQLException {
        return new DataSourceTransactionManager(create${module?cap_first}Datasource());
    }


    // 事务拦截类型 
    /*@Bean
    public TransactionAttributeSource create${module?cap_first}TransactionAttributeSource() {
        NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();
        // 只读事务，不做更新操作 
        final RuleBasedTransactionAttribute NOT_SUPPORTED = new RuleBasedTransactionAttribute();
        NOT_SUPPORTED.setReadOnly(true);
        NOT_SUPPORTED.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED);
        // 当前存在事务就使用当前事务，当前不存在事务就创建一个新的事务 
        // RuleBasedTransactionAttribute requiredTx = new
        // RuleBasedTransactionAttribute();
        // requiredTx.setRollbackRules(
        // Collections.singletonList(new
        // RollbackRuleAttribute(Exception.class)));
        // requiredTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        final RuleBasedTransactionAttribute SUPPORTS = new RuleBasedTransactionAttribute();
        SUPPORTS.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
        final RuleBasedTransactionAttribute REQUIRES_NEW = new RuleBasedTransactionAttribute();
        REQUIRES_NEW.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
        
        final RuleBasedTransactionAttribute REQUIRED = new RuleBasedTransactionAttribute(
                TransactionDefinition.PROPAGATION_REQUIRED,
                Collections.singletonList(new RollbackRuleAttribute(Exception.class)));
        //REQUIRED.setTimeout(5);
        Map<String, TransactionAttribute> txMap = new LinkedHashMap<>(32);
        txMap.put("select*", SUPPORTS);
        txMap.put("find*", SUPPORTS);
        txMap.put("get*", SUPPORTS);
        txMap.put("load*", SUPPORTS);
        txMap.put("count*", SUPPORTS);
        txMap.put("list*", SUPPORTS);
        txMap.put("not*", NOT_SUPPORTED);
        txMap.put("unLockDispatch*", REQUIRES_NEW);
        txMap.put("*", REQUIRED);
        
        source.setNameMap(txMap);
        return source;
    }

    // 事务拦截器 
    @Bean("${module}TxInterceptor")
    public TransactionInterceptor createEcejServiceTransactionInterceptor(@Qualifier("${module?cap_first}TransactionManager")PlatformTransactionManager tx) {
        return new TransactionInterceptor(tx, this.create${module?cap_first}TransactionAttributeSource());
    }

    // 切面拦截规则 参数会自动从容器中注入 
    @Bean
    public AspectJExpressionPointcutAdvisor createPointcutAdvisor(@Qualifier("${module}TxInterceptor")TransactionInterceptor txInterceptor) {
        AspectJExpressionPointcutAdvisor pointcutAdvisor = new AspectJExpressionPointcutAdvisor();
        pointcutAdvisor.setAdvice(txInterceptor);
        pointcutAdvisor.setExpression("execution(* com.${ltdAbbr}.xiao.${module}.dal.service..*.*(..)) or execution(* com.${ltdAbbr}.xiao.${module}.bo.service..*.*(..)) and !execution(* com.${ltdAbbr}.xiao.${module}.dal.dao..*.*(..)) ");
        return pointcutAdvisor;
    }*/
}
